package com.backend.controllers;

import com.backend.models.*;
import com.backend.struts.GlobalDefine;
import com.backend.struts.HttpParams;
import com.backend.utils.CommonStringUtils;
import com.backend.utils.UserManageUtils;
import com.google.gson.Gson;
import com.qiniu.util.StringUtils;
import io.ebean.Ebean;
import io.ebean.ExpressionList;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import static com.backend.struts.GlobalDefine.SORT_CONDITION;

@RestController
public class AppInterfaceController {
    @RequestMapping(value = "/app/get_product_genres/", method = RequestMethod.GET)
    @ResponseBody
    public String getProductGenres() {
        Logger.getGlobal().info("get Genre is ok!");
        List<String> proGenres = ProductGenre.search().eq("deleted", false).select("name").findSingleAttributeList();
        return new Gson().toJson(proGenres);
    }

    @RequestMapping(value = "/app/add_product/", method = RequestMethod.POST)
    @ResponseBody
    public String addProduct(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        String proTitle = params.getParam("title", "");
        String description = params.getParam("description", "");
        Integer integrity = params.getIntParam("integrity", 100);
        Double salePrice = params.getDoubleParam("sale_price");
        Double buyPrice = params.getDoubleParam("buy_price");
        Double expressFee = params.getDoubleParam("express_fee", 0.00);
        String genreName = params.getParam("genre");
        Boolean needSelf = params.getBooleanParam("need_self");
        Boolean needMeet = params.getBooleanParam("need_meet");
        Boolean needExpress = params.getBooleanParam("need_express");
        String images = params.getParam("images");
        String showImgPath = params.getParam("show_img_path");
        Double lat = params.getDoubleParam("lat", 0.0D);
        Double lng = params.getDoubleParam("lng", 0.0D);
        if (userId == 0 || salePrice == null || genreName == null || images == null || showImgPath == null) {
            return "error";
        }
        List<String> imagePath = Arrays.stream(images.split(",")).collect(Collectors.toList());
        ProductGenre genre = ProductGenre.search().eq("name", genreName).eq("deleted", false).findOne();
        Product product = new Product();
        product.title = proTitle;
        product.description = description;
        product.integrity = integrity;
        product.price = salePrice;
        product.buyPrice = buyPrice;
        product.expressFee = expressFee;
        product.genre = genre;
        product.needSelf = needSelf;
        product.needMeet = needMeet;
        product.needExpress = needExpress;
        product.showImg = showImgPath;
        product.createTime = new Date();
        product.userId = userId;
        product.status = GlobalDefine.PRODUCT_STATUS.insale;
        product.lat = lat;
        product.lng = lng;
        product.save();
        int order = 1;
        for (String path : imagePath) {
            ImageStorge imageStorge = new ImageStorge();
            imageStorge.boomId = product.id;
            imageStorge.path = path;
            imageStorge.orderNum = order;
            imageStorge.category = ImageStorge.IMAGE_TYPE.PRODUCT;
            imageStorge.save();
            order++;
        }
        return "success";
    }

    @RequestMapping(value = "/app/get_products_info/", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String getProductsInfo(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        String productIds = params.getParam("poduct_ids", "");
        Integer count = params.getIntParam("count", 10);
        Integer userId = params.getIntParam("user_id", 0);
        Integer distance = params.getIntParam("distance");
        String genre = params.getParam("genre");
        Double minPrice = params.getDoubleParam("min_price");
        Double maxPrice = params.getDoubleParam("max_price");
        String name = params.getParam("title");
        String sort = params.getParam("sort", "recommend");
        Boolean isNoExpressFee = params.getBooleanParam("is_free_express", false);
        Boolean isAllNew = params.getBooleanParam("is_all_new", false);
        List<Map<String, String>> result = new ArrayList<>();
        if (count == 0) {
            return new Gson().toJson(result);
        }
        List<Integer> ids = Arrays.stream(productIds.split(",")).map(CommonStringUtils::safeInteger).collect(Collectors.toList());
        ExpressionList<Product> productExpressionList = Product.search().notIn("id", ids).eq("status", GlobalDefine.PRODUCT_STATUS.insale);
        if (distance != null) {

        }
        if (!StringUtils.isNullOrEmpty(genre)) {
            GlobalDefine.GENRE_TYPE genreType = GlobalDefine.GENRE_TYPE.getObject(genre);
            if (genreType != null) {
                productExpressionList.eq("genre.name", genreType.getGenreName());
            }else{
                productExpressionList.eq("genre.name", genre);
            }
        }
        if (!StringUtils.isNullOrEmpty(name)) {
            productExpressionList.icontains("title", name);
        }
        if (minPrice != null) {
            productExpressionList.ge("price", minPrice);
        }
        if (maxPrice != null) {
            productExpressionList.le("price", maxPrice);
        }
        if (isNoExpressFee) {
            productExpressionList.eq("expressFee", 0D);
        }
        if (isAllNew) {
            productExpressionList.eq("integrity", 100);
        }
        GlobalDefine.SORT_CONDITION condition = GlobalDefine.SORT_CONDITION.getObjectByName(sort);
        if (condition != null) {
            switch (condition) {
                case recommend: {
                    productExpressionList.orderBy("popularity desc");
                    break;
                }
                case price_asc: {
                    productExpressionList.orderBy("price asc");
                    break;
                }
                case price_desc: {
                    productExpressionList.orderBy("price desc");
                    break;
                }
                case distance_near: {
                    break;
                }
                default:
                    break;
            }
        }
        productExpressionList.setFirstRow(0).setMaxRows(count);
        List<Product> products = productExpressionList.findList();
        List<Object> userIds = products.stream().map(product -> product.userId).distinct().collect(Collectors.toList());
        String userJson = UserManageUtils.getGetUsersInfoByIds(CommonStringUtils.join(userIds, ","));
        Map<String, Map<String, String>> userInfos = new HashMap<>();
        try {
            userInfos = new Gson().fromJson(userJson, Map.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<ProductCollect> productCollects = ProductCollect.search().in("product", products).eq("userId", userId).findList();
        Map<Product, ProductCollect> collectMap = productCollects.stream().collect(Collectors.toMap(o1 -> o1.product, o1 -> o1));
        for (Product product : products) {
            Map<String, String> map = userInfos.getOrDefault(CommonStringUtils.safeString(product.userId), new HashMap<>());
            Map<String, String> info = new HashMap<>();
            info.put("title", CommonStringUtils.safeString(product.title));
            info.put("username", CommonStringUtils.safeString(map.get("username")));
            info.put("show_img", CommonStringUtils.safeString(product.showImg));
            info.put("price", CommonStringUtils.safeString(product.price));
            info.put("user_img", CommonStringUtils.safeString(map.get("img_path")));
            info.put("user_id", CommonStringUtils.safeString(product.userId));
            info.put("pro_id", CommonStringUtils.safeString(product.id));
            info.put("buy_price", CommonStringUtils.safeString(product.buyPrice));
            info.put("express_fee", CommonStringUtils.safeString(product.expressFee));
            info.put("status",product.status.name());
            info.put("is_collected", collectMap.get(product) == null ? "0" : collectMap.get(product).isCollected ? "1" : "0");
            result.add(info);
        }
        return new Gson().toJson(result);
    }

    @RequestMapping(value = "/app/refresh_products_view/", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String refreshProducts(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id",0);
        List<Product> productList = Product.search().eq("status", GlobalDefine.PRODUCT_STATUS.insale)
                .orderBy("createTime desc").setFirstRow(0).setMaxRows(5).findList();
        List<ProductCollect> productCollects = ProductCollect.search().in("product",productList).eq("userId",userId).findList();
        Map<Product, ProductCollect> collectMap = productCollects.stream().collect(Collectors.toMap(o1 -> o1.product, o1 -> o1));
        List<Object> userIds = productList.stream().map(product -> product.userId).distinct().collect(Collectors.toList());
        String userJson = UserManageUtils.getGetUsersInfoByIds(CommonStringUtils.join(userIds, ","));
        Map<String, Map<String, String>> userInfos = new HashMap<>();
        List<Map<String, String>> result = new ArrayList<>();
        try {
            userInfos = new Gson().fromJson(userJson, Map.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        for (Product product : productList) {
            Map<String, String> map = userInfos.getOrDefault(CommonStringUtils.safeString(product.userId), new HashMap<>());
            Map<String, String> info = new HashMap<>();
            info.put("title", CommonStringUtils.safeString(product.title));
            info.put("username", CommonStringUtils.safeString(map.get("username")));
            info.put("show_img", CommonStringUtils.safeString(product.showImg));
            info.put("price", CommonStringUtils.safeString(product.price));
            info.put("user_img", CommonStringUtils.safeString(map.get("img_path")));
            info.put("user_id", CommonStringUtils.safeString(product.userId));
            info.put("pro_id", CommonStringUtils.safeString(product.id));
            info.put("buy_price", CommonStringUtils.safeString(product.buyPrice));
            info.put("express_fee", CommonStringUtils.safeString(product.expressFee));
            info.put("status",product.status.name());
            info.put("is_collected", collectMap.get(product) == null ? "0" : collectMap.get(product).isCollected ? "1" : "0");
            result.add(info);
        }
        return new Gson().toJson(result);
    }


    @RequestMapping(value = "/app/get_product_by_id/", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
    @ResponseBody
    public String getProductById(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer productId = params.getIntParam("product_id",0);
        Integer userId = params.getIntParam("user_id",0);
        ProductCollect productCollect = ProductCollect.search().eq("product.id",productId).eq("userId",userId).findOne();
        Product product = Product.find.byId(productId);
        Map<String, String> info = new HashMap<>();
        if(product != null) {
            String userJson = UserManageUtils.getGetUsersInfoByIds(product.userId.toString());
            Map<String, Map<String, String>> userInfos = new HashMap<>();
            try {
                userInfos = new Gson().fromJson(userJson, Map.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
            Map<String,String> map = userInfos.getOrDefault(CommonStringUtils.safeString(product.userId), new HashMap<>());
            info.put("title", CommonStringUtils.safeString(product.title));
            info.put("username", CommonStringUtils.safeString(map.get("username")));
            info.put("show_img", CommonStringUtils.safeString(product.showImg));
            info.put("price", CommonStringUtils.safeString(product.price));
            info.put("user_img", CommonStringUtils.safeString(map.get("img_path")));
            info.put("user_id", CommonStringUtils.safeString(product.userId));
            info.put("pro_id", CommonStringUtils.safeString(product.id));
            info.put("buy_price", CommonStringUtils.safeString(product.buyPrice));
            info.put("express_fee", CommonStringUtils.safeString(product.expressFee));
            info.put("status", product.status.name());
            info.put("is_collected", productCollect != null && productCollect.isCollected ? "1" : "0");
        }
        return new Gson().toJson(info);
    }

    @RequestMapping(value = "/app/add_commet/", method = RequestMethod.POST)
    @ResponseBody
    public String addComment(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        String comment = params.getParam("comment");
        Integer reCommentId = params.getIntParam("recomment_id", 0);
        Integer productId = params.getIntParam("product_id", 0);

        Product product = Product.find.byId(productId);

        if (StringUtils.isNullOrEmpty(comment)) {
            return "invalid comment";
        } else if (userId == 0) {
            return "no user";
        } else if (product == null) {
            return "error";
        }
        product.setPopularity(product.popularity + 5);
        product.save();
        ProductComment reProductComment = ProductComment.find.byId(reCommentId);
        ProductComment productComment = new ProductComment();
        productComment.userId = userId;
        productComment.comment = comment;
        productComment.createTime = new Date();
        productComment.product = product;
        productComment.reComment = reProductComment;
        productComment.deleted = false;
        productComment.save();
        return "success";
    }

    @RequestMapping(value = "/app/collect_product/", method = RequestMethod.GET)
    @ResponseBody
    public String productCollect(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        Integer productId = params.getIntParam("product_id", 0);
        Integer isCollect = params.getIntParam("is_collect", 0);
        Logger.getGlobal().info("Collect: " + isCollect);
        Product product = Product.find.byId(productId);
        if (userId == 0 || product == null) {
            return "error";
        }
        ProductCollect productCollect = ProductCollect.search().eq("userId", userId).eq("product", product).findOne();
        if (productCollect == null) {
            productCollect = new ProductCollect();
            productCollect.setProduct(product);
            productCollect.setUserId(userId);
        }
        productCollect.setCollected(isCollect == 0 ? false : true);
        productCollect.setLastModifyTime(new Date());
        productCollect.save();
        if (productCollect.isCollected) {
            product.setPopularity(product.popularity + 5);
        } else {
            product.setPopularity(product.popularity - 5);
        }
        product.save();
        return "success";
    }

    @RequestMapping(value = "/app/get_product_info_by_id/", method = RequestMethod.GET)
    @ResponseBody
    public String getProductInfoById(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        Integer productId = params.getIntParam("product_id", 0);
        Product product = Product.find.byId(productId);
        Map<String, String> resMap = new HashMap<>();
        ProductCollect productCollect = ProductCollect.search().eq("product", product).eq("userId", userId).findOne();
        resMap.put("product_id", CommonStringUtils.safeString(productId));
        resMap.put("is_collected", productCollect == null ? "0" : productCollect.isCollected ? "1" : "0");
        return new Gson().toJson(resMap);
    }

    @RequestMapping(value = "/app/get_delivery_addresses/", method = RequestMethod.POST)
    @ResponseBody
    public String getDeliveryAddresses(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        List<DeliveryAddress> deliveryAddresses = DeliveryAddress.search().eq("userId", userId).eq("deleted", false).orderBy("lastModifyTime desc").findList();
        List<Map<String, String>> maps = deliveryAddresses.stream().map(address -> address.getInfoMap()).collect(Collectors.toList());
        return new Gson().toJson(maps);
    }

    @RequestMapping(value = "/app/get_default_delivery_addresses/", method = RequestMethod.POST)
    @ResponseBody
    public String getDefaultDeliveryAddresses(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id", 0);
        DeliveryAddress deliveryAddress = DeliveryAddress.search().eq("userId", userId).eq("deleted", false).eq("isDefault",true).findOne();
        if(deliveryAddress == null){
            return "{}";
        }
        return new Gson().toJson(deliveryAddress.getInfoMap());
    }

    @RequestMapping(value = "/app/create_ortder/", method = RequestMethod.POST)
    @ResponseBody
    public String createOrder(HttpServletRequest request){
        HttpParams params = new HttpParams(request);
        Integer userId = params.getIntParam("user_id",0);
        Integer productId = params.getIntParam("product_id",0);
        Integer deliveryAddressId = params.getIntParam("delivery_address_id",0);
        Product product = Product.find.byId(productId);
        DeliveryAddress deliveryAddress = DeliveryAddress.find.byId(deliveryAddressId);
        Map<String,String> resMap = new HashMap<>();
        if(userId == 0 || product == null || deliveryAddress == null){
            resMap.put("status","error");
            return new Gson().toJson(resMap);
        }
        if(product.status != GlobalDefine.PRODUCT_STATUS.insale){
            resMap.put("status","saled");
            return new Gson().toJson(resMap);
        }
        Order order = new Order();
        order.createTime = new Date();
        order.product = product;
        order.userId = userId;
        order.deliveryAddress = deliveryAddress;
        order.expressFee = product.expressFee;
        order.price = product.price;
        order.salerId = product.userId;
        order.saleStatus = Order.SALE_STATUS.payed;
        order.save();
        resMap.put("status","success");
        product.setStatus(GlobalDefine.PRODUCT_STATUS.saling);
        product.save();
        return new Gson().toJson(resMap);
    }

    @RequestMapping(value = "/app/collect_by_collect_id/", method = RequestMethod.POST)
    @ResponseBody
    public String collectByCollectId(HttpServletRequest request){
        HttpParams params = new HttpParams(request);
        Integer collectId = params.getIntParam("collect_id",0);
        String value = params.getParam("value");
        ProductCollect collect = ProductCollect.find.byId(collectId);
        String msg = "error";
        if(collect == null || (!"true".equals(value) && !"false".equals(value))){
            return msg;
        }
        Ebean.beginTransaction();
        try {
            collect.setCollected(Boolean.valueOf(value));
            collect.setLastModifyTime(new Date());
            collect.save();
            Ebean.commitTransaction();
            msg = "success";
        }catch (Exception e){
            Ebean.rollbackTransaction();
            Logger.getGlobal().log(Level.WARNING,e.getMessage());
        }finally {
            Ebean.endTransaction();
        }
        return msg;
    }

    @RequestMapping(value = "/app/get_educations_info/",produces = "application/json;charset=UTF-8",method = RequestMethod.GET)
    @ResponseBody
    public String getEducations(HttpServletRequest request) {
        HttpParams params = new HttpParams(request);
        String province = params.getParam("province");
        String city = params.getParam("city");
        if(StringUtils.isNullOrEmpty(province) || StringUtils.isNullOrEmpty(city)){
            return "[]";
        }
        String res = UserManageUtils.getSchoolsInfo(province,city);
        return res;
    }
}
